package com.xbh.management.aspect;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nimbusds.jose.JOSEException;
import com.xbh.management.exception.JwtSignatureVerifyException;
import com.xbh.management.handler.RabbitMQTest;
import com.xbh.management.model.ManMenu;
import com.xbh.management.model.ManOperationLog;
import com.xbh.management.service.ManOperationLogService;
import com.xbh.management.service.MenuService;
import com.xbh.management.utils.JwtUtilManagement;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.List;

/**
 * @program: management-center
 * @description:
 * @author: 许宝华
 * @create: 2021-09-08 17:13
 */

@Aspect
@Component
@Slf4j
public class LogHandle {


    @Autowired
    private ManOperationLogService manOperationLogService;

    @Autowired
    private MenuService menuService;

    //切入点,对controller下所有请求都进行拦截
    // * com.xbh.management.controller..*.*(..))第一个*代表返回的类型可以是任意的，
    // controller后面的..代表包service以及下面的所有子包，*代表这些包下面的所有类；
    // .*代表所有这些类下面的所有方法；（..）代表这些方法的输入参数可以是0或多个.
    // && !execution(* com.xbh.management.controller..*.saveCode(..))
    @Pointcut(value = "execution(* com.xbh.management.controller..*.*(..))")
    public void start() {

    }


    /**
     * 环绕通知
     * 环绕通知非常强大，可以决定目标方法是否执行，什么时候执行，执行时是否需要替换方法参数，执行完毕是否需要替换返回值。
     * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     * @param proceedingJoinPoint
     */
    @Before("start()")
    public void access(JoinPoint joinPoint) throws ParseException, JOSEException, JwtSignatureVerifyException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String url = request.getRequestURL().toString();
        int index = request.getRequestURL().toString().lastIndexOf("8803")+4;

        if(! url.substring(index).equals("/user/getImage") && ! url.substring(index).equals("/user/code") && ! url.substring(index).equals("/user/selectUserRelationAllMenuBy")){
            LambdaQueryWrapper<ManMenu> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ManMenu::getOpenAddress,url.substring(index));
            List<ManMenu> list = menuService.list(wrapper);
            StringBuilder stringBuilder = new StringBuilder();
            list.stream().forEach(menu ->{
                stringBuilder.append(menu.getMenuName());
            });
            //操作日志
            ManOperationLog manOperationLog = new ManOperationLog();
            manOperationLog.setUsername(JwtUtilManagement.getUsername());
            manOperationLog.setUserId(JwtUtilManagement.getUserId());
            manOperationLog.setOperationTitle("操作成功");
            manOperationLog.setOperationInfo(stringBuilder.toString());
            manOperationLog.setNodeColor("green");
            manOperationLog.setCreatePerson(JwtUtilManagement.getUsername());
            manOperationLog.setUpdatePerson(JwtUtilManagement.getUsername());
            manOperationLogService.save(manOperationLog);
        }
    }

    /**
     * 获取参数
     *
     * @param key
     * @return
     */
    private Object getParams(String key) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String header = request.getHeader(key);
        return header;
    }

    /**
     * 判断某方法上是否含有某注解
     *
     * @param method
     * @param annotationClazz
     * @return
     */
    private boolean hasAnnotationOnMethod(Method method, Class annotationClazz) {
        //使用反射获取注解信息
        Annotation a = method.getAnnotation(annotationClazz);
        if (a == null) {
            return false;
        }
        return true;
    }
}
